package qj.app.trader;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import qj.util.Cols;
import qj.util.LanguageUtil;
import qj.util.StringUtil;
import qj.util.funct.F1;

public class ParseRule {
	MatchProposes proposes = new MatchProposes();
	public RuleMatch apply(String expandContent, Reader reader) {
		return apply(expandContent, reader, proposes);
	}
	
	public static class RuleMatch {
		public List<MatchPropose> proposes;
		public String attrName;
		public String val;

		public RuleMatch(String name, String val) {
			this.attrName = name;
			this.val = val;
		}
		
	}

	static boolean DEBUG = false;
	public RuleMatch apply(String expandContent, Reader reader, MatchProposes proposals) {
		RuleMatch applyRaw = applyRaw(tokenize(expandContent), expandContent, reader, proposals);
		if (applyRaw != null) {
			return applyRaw;
		}
		applyRaw = applyRaw(tokenize(normalize(expandContent)), expandContent, reader, proposals);
		if (applyRaw != null) {
			return applyRaw;
		}
		applyRaw = applyRaw(tokenize(normalizeVal(expandContent)), expandContent, reader, proposals);
		return applyRaw;
	}
	private RuleMatch applyRaw(List<String> normalizeVal, String expandContent,
			Reader reader, MatchProposes proposals) {
		List<MatchPropose> list = proposals.index.get(normalizeVal);
		if (Cols.isEmpty(list)) {
			return null;
		}
		return toMatch(list, reader, expandContent);
	}
	
	private RuleMatch toMatch(List<MatchPropose> list, Reader reader,
			String expandContent) {
		RuleMatch ruleMatch = new RuleMatch(Cols.getSingle(list).name, expandContent);
		return ruleMatch;
	}
	
	public static class MatchProposes {
		Map<List<String>,List<MatchPropose>> index = new HashMap<List<String>, List<MatchPropose>>();

		public void addPropose(List<String> val, MatchPropose matchPropose) {
			List<MatchPropose> list = index.get(val);
			if (list == null) {
				list = new LinkedList();
				index.put(val, list);
			}
			list.add(matchPropose);		
		}
	}

	protected static class MatchPropose {

		private String name; // TODO duplicated with Attr
		
		public F1<String, String> parser;
		public boolean sure = true;

		public MatchPropose(String name) {
			this.name = name;
		}

		public MatchPropose setParser(F1<String,String> parser) {
			this.parser = parser;
			return this;
		}
		
	}

	public static String normalize(String val) {
		return LanguageUtil.removeViMark(StringUtil.innerTrim(val.toLowerCase()));
	}
	private List<String> tokenize(String val) {
		LinkedList<String> tokens = new LinkedList<String>();
		for (String token : val.split("\\s+")) {
			tokens.add(token);
		}
		return tokens;
	}
	public static LinkedList<String> normalizeKey(String val) {
		LinkedList<String> key = new LinkedList<String>();
		String normalizedStr = normalize(val);
		for (String token : normalizedStr.split("\\s+")) {
			key.add(token.replaceAll("[()]", ""));
		}
		return key;
	}
	public static String normalizeVal(String val) {
		return normalize(val).replaceAll("[\\d,.]+", "\\\\d+");
	}
	
}
